﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UMLTouch.Core;
using UMLTouch.Core.Entities;
using UMLTouch.DomainRecognition;
using System.Data;
using System.Windows;
using UMLTouch.DomainRecognition.ShapeRecognition;

namespace UMLTouch.DomainRecognition.Engines
{
    public class ShapeRecognitionEngine : AbstractEngine<SegmentedStroke, Shape>
    {

        //List<IShapePattern> _shapePatterns;
        Shape _currentShape;
        Shape _previouslyMatchedShape;
        //IShapePattern _previouslyMatchedPattern;
        ShapeRecognizer _recognizer;



        public ShapeRecognitionEngine(ShapeRecognizer recognizer)
            : base()
        {

            //_shapePatterns = new List<IShapePattern>();
            _currentShape = null;
            _previouslyMatchedShape = null;
            //_shapePatterns.Add(new SquarePattern());
            //_shapePatterns.Add(new TrianglePattern());
            _recognizer = recognizer;
        }



        public override void SpecificRecognition(SegmentedStroke seg)
        {

            //foreach (Segment s in seg.Segments)
            //{

            Boolean keepOn = true;

            if (_currentShape == null)
            {
                _currentShape = new Shape();
            }

            _currentShape.AddRangeSegments(seg.Segments);

            while (keepOn)
            {
                keepOn = false;
                var patterns = _recognizer.Match(_currentShape);

                switch (patterns.Count())
                {
                    case 0:
                        //the shape can't be recognized
                        if (_previouslyMatchedShape != null)
                        {
                            PushOutput(_previouslyMatchedShape);
                            _currentShape = new Shape(seg.Segments);
                            keepOn = true;
                        }
                        else
                        {
                            PushOutput(_currentShape);
                        }
                        break;
                    case 1:
                        ShapeMatchingResult res = patterns.First();
                        if (res.Matching == ShapePatternMatchingResultEnum.Match)
                        {
                            //we found the only matching pattern;
                            _currentShape.ShapePattern = res.MatchingPattern;
                            PushOutput(_currentShape);
                            //_previouslyMatchedShape = new Shape(_currentShape);
                            //_previouslyMatchedShape.ShapePattern = res.MatchingPattern;
                        }
                        break;
                    default:
                        var q = patterns.Where(p => p.Matching == ShapePatternMatchingResultEnum.Match);

                        if (q.Count() == 1)
                        {
                            //we found a potential matching pattern but there are also might matching patterns,
                            //so we save the state of the current shape with the recognized pattern and keep on annalysing the
                            //new strokes
                            _previouslyMatchedShape = new Shape(_currentShape);
                            _previouslyMatchedShape.ShapePattern = q.First().MatchingPattern;
                        }
                        break;
                }
            }
            //}
            #region Backup

            //var matchingPatterns = from patt in _shapePatterns
            //                       where patt.Match(_currentShape) == ShapePatternMatchingResultEnum.Match
            //                       select patt;

            //switch (matchingPatterns.Count())
            //{
            //    case 0:
            //        if (_previouslyMatchedShape != null)
            //        {
            //            //the previous pattern was correct
            //            _previouslyMatchedShape.ShapePattern = _previouslyMatchedPattern;                        
            //            PushOutput(_previouslyMatchedShape);
            //            _currentShape = new Shape(seg.Segments);
            //            _previouslyMatchedShape = null;
            //            _previouslyMatchedPattern = null;
            //            return;
            //        }
            //        break;
            //    case 1:
            //        _previouslyMatchedShape = new Shape(_currentShape);
            //        _previouslyMatchedPattern = matchingPatterns.First();

            //        Console.WriteLine("match " + _previouslyMatchedPattern.ToString());
            //        break;
            //    default:
            //        throw new Exception("can't have several matching patterns");
            //}

            //if (_currentShape != null)
            //{
            //    var mightMatchingPatterns = from patt in _shapePatterns
            //                                where patt.Match(_currentShape) == ShapePatternMatchingResultEnum.MightMatch
            //                                select patt;

            //    if (mightMatchingPatterns.Count() == 0)
            //    {
            //        if (_previouslyMatchedShape != null)
            //        {
            //            //we have one matching pattern and 0 mightMatching. 
            //            //This means that the _currentShape has been correctly recognized
            //            _currentShape.ShapePattern = _previouslyMatchedPattern;
            //            PushOutput(_currentShape);
            //            _currentShape = null;
            //            _previouslyMatchedShape = null;
            //            _previouslyMatchedPattern = null;
            //        }
            //        else
            //        {
            //            //there are no matching patterns and no might matching patterns.
            //            // this means that the currentShape can't be recognized
            //            throw new Exception("This shape can't be recognized in this context !");
            //        }
            //    }
            //    else
            //    {
            //        //debug
            //        //there are several might matching patterns
            //        StringBuilder sb = new StringBuilder();
            //        sb.Append("might match : ");
            //        foreach (var item in mightMatchingPatterns)
            //        {
            //            sb.AppendFormat("{0} ", item.ToString());
            //        }
            //        Console.WriteLine(sb.ToString());
            //    }
            //} 
            #endregion
        }

        public override void PushOutput(Shape output)
        {
            base.PushOutput(output);
            _currentShape = null;
            _previouslyMatchedShape = null;
        }

    }
}
